﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace Useful.GUI
{
    public static class DataGridViewHelper
    {
        public static void CreateColumns(DataGridView grid, Type type)
        {
            grid.Columns.Clear();

            AddColumns(grid, type);
        }

        public static void AddColumns(DataGridView grid, Type type)
        {
            List<PropertyInfo> _props = new List<PropertyInfo>(type.GetProperties(BindingFlags.Instance | BindingFlags.Public));

            List<PropertyInfo> props = _props.FindAll(pi =>
            {
                bool res = false;
                object[] attributes = pi.GetCustomAttributes(typeof(ExDisplayNameAttribute), false);

                if (attributes.Length == 1)
                    res = true;

                return res;
            });

            props.Sort((piX, piY) =>
            {
                object[] attributesX = piX.GetCustomAttributes(typeof(ExDisplayNameAttribute), false);
                object[] attributesY = piY.GetCustomAttributes(typeof(ExDisplayNameAttribute), false);

                if (attributesX.Length == 1 && attributesY.Length == 1)
                {
                    ExDisplayNameAttribute aX = (ExDisplayNameAttribute)attributesX[0];
                    ExDisplayNameAttribute aY = (ExDisplayNameAttribute)attributesY[0];

                    return Comparer<int>.Default.Compare(aX.Order, aY.Order);
                }
                else
                    throw new Exception("attributesX.Length != 1 || attributesY.Length != 1");
            });

            foreach (PropertyInfo pi in props)
            {
                object[] attributes = pi.GetCustomAttributes(typeof(ExDisplayNameAttribute), false);
                ExDisplayNameAttribute a = (ExDisplayNameAttribute)attributes[0];

                string toolTipText = null;

                object[] attributes2 = pi.GetCustomAttributes(typeof(ToolTipAttrubute), false);
                if (attributes2.Length != 0)
                {
                    ToolTipAttrubute tta = (ToolTipAttrubute)attributes2[0];
                    toolTipText = tta.ToolTipText;
                }

                string colName = a.ColumnName ?? pi.Name;

                if (pi.PropertyType == typeof(bool?))
                    AddNullBoolColumn(grid, colName, a.DisplayName, pi.Name, a.AutoSizeColumn, toolTipText);
                else if (pi.PropertyType == typeof(bool))
                    AddBoolColumn(grid, colName, a.DisplayName, pi.Name, a.AutoSizeColumn, toolTipText);
                else if (pi.PropertyType == typeof(DateTime))
                    AddCalendarTextColumn(grid, colName, a.DisplayName, pi.Name, DataGridViewAutoSizeColumnMode.AllCells, toolTipText);
                else
                    AddTextColumn(grid, colName, a.DisplayName, pi.Name, a.AutoSizeColumn, a.Format, toolTipText);

                grid.Columns[colName].ReadOnly = a.ReadOnly;
            }
        }

        public static DataGridViewTextBoxColumn AddTextColumn(DataGridView grid, string name, string header, string dataPropertyName, DataGridViewAutoSizeColumnMode sizeMode, string format, string toolTipText)
        {
            DataGridViewTextBoxColumn res = new DataGridViewTextBoxColumn();

            AddColumn(grid, res, name, header, dataPropertyName, sizeMode, toolTipText, format);

            return res;
        }

        public static DataGridViewCalendarTextColumn AddCalendarTextColumn(DataGridView grid, string name, string header, string dataPropertyName, DataGridViewAutoSizeColumnMode sizeMode, string toolTipText)
        {
            DataGridViewCalendarTextColumn res = new DataGridViewCalendarTextColumn();

            AddColumn(grid, res, name, header, dataPropertyName, sizeMode, toolTipText, null);

            return res;
        }

        public static DataGridViewNullCheckBoxColumn AddNullBoolColumn(DataGridView grid, string name, string header, string dataPropertyName, DataGridViewAutoSizeColumnMode sizeMode, string toolTipText)
        {
            DataGridViewNullCheckBoxColumn res = new DataGridViewNullCheckBoxColumn();

            AddColumn(grid, res, name, header, dataPropertyName, sizeMode, toolTipText);

            res.ThreeState = true;

            return res;
        }

        public static DataGridViewCheckBoxColumn AddBoolColumn(DataGridView grid, string name, string header, string dataPropertyName, DataGridViewAutoSizeColumnMode sizeMode, string toolTiptext)
        {
            DataGridViewCheckBoxColumn res = new DataGridViewCheckBoxColumn();

            AddColumn(grid, res, name, header, dataPropertyName, sizeMode, toolTiptext);

            res.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;

            return res;
        }

        private static void AddColumn(DataGridView grid, DataGridViewColumn column, string name, string header, string dataPropertyName, DataGridViewAutoSizeColumnMode? sizeMode, string toolTipText)
        {
            AddColumn(grid, column, name, header, dataPropertyName, sizeMode, toolTipText, null);
        }

        private static void AddColumn(DataGridView grid, DataGridViewColumn column, string name, string header, string dataPropertyName, DataGridViewAutoSizeColumnMode? sizeMode, string toolTipText, string format)
        {
            GuiHelper.DataGridViewAddColumn(grid, column, name, header, dataPropertyName, sizeMode, toolTipText, format);
        }
    }
}
